package com.wanghua.spring.dao;

import com.wanghua.spring.bean.entity.VisitOnline;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;

import java.util.Date;
import java.util.List;

//由于Spring 3.x 对 Hibernate 4.x 不提供 HibernateDaoSupport，所以在dao的实现层注入SessionFactory，由于SessionFactory不是自己定义的类，所以只能在XML中定义bean了。
//HibernateDaoSupport 似乎只能放某个具体的DAO中，不能定义一个基类extends  HibernateDaoSupport，再 “DaoImpl extends 基类”
public class DaoImpl extends HibernateDaoSupport implements IDao {
    /*
    * EntityManager 的作用相当于 Hibernate 中的 Session，负责持久化、更新、查询、删除实体。
    * JPA 容器会自动向标记了 @PersistenceContext 的属性注射 EntityManager 资源。PersistenceContext 需要在 META-INF/persistence.xml 文件中配置一下。
    * 如果使用 JPA 规范中的 @PersistenceContext,那么不需要使用 extends HibernateDaoSupport 了。
    * */
    //@PersistenceContext   //@PersistenceContext 接受容器资源注射
    //protected EntityManager em;

    @Override
    public void create(Object obj) {
        //       em.persist(obj);

        //建议：当方法不需要事务（aop-tx）支持的时候，使用 getSessionFactory().openSession()来获得Session对象。getSessionFactory().getCurrentSession() 会报错。当方法使用事物时，可使用 getSessionFactory().getCurrentSession()。
        Session session = getSessionFactory().getCurrentSession();
        //Session session = getSessionFactory().openSession();
        //session.beginTransaction();
        //session.save();
        //1.persist把一个瞬态的实例持久化，但是并"不保证"标识符(identifier主键对应的属性)被立刻填入到持久化实例中，标识符的填入可能被推迟到flush的时候。 2，save, 把一个瞬态的实例持久化标识符，及时的产生,它要返回标识符，所以它会立即执行Sql insert
        session.persist(obj); //会执行"insert into"语句，不会执行"update"语句。
        //session.flush(); 使用事物后，不需要这句就会执行SQL
        //session.getTransaction().commit();
        //session.close();
    }

    @Override
    public void save(Object obj) {
        Session session = getSessionFactory().getCurrentSession();
        //session.saveOrUpdate()
        session.merge(obj); //会执行"update"或"insert"。merge 和 saveOrUpdate不一样，当session中某持久化对象有id相同的两个纪录时，必须用merge，merge会在保存之前来合并记录，不然会报错。合并记录后的动作和saveOrUpdate一样
        //session.flush(); 使用事物后，不需要这句就会执行SQL
    }

    @Override
    public int removeTimedOutOnlineRecords() {
        Session session = getSessionFactory().getCurrentSession();
        Query query = session.createQuery("update VisitOnline v set v.online=false where v.online=true and v.lastActiveDate<:lastActiveDate").setParameter("lastActiveDate", new Date(System.currentTimeMillis() - TIME_OUT));
        int result = query.executeUpdate();
        return result;

        /*
        int v = 0;
        try {
            //执行下面方法程序挂掉了，而且也不报任何异常。必须用 Throwable 才能捕获到：org.springframework.orm.hibernate4.SessionHolder cannot be cast to org.springframework.orm.hibernate3.SessionHolder。
            //在dao层如果用sessionFactory.getCurrentSession().save()方法保存数据，不会报错。但是用 getHibernateTemplate().save()就会报。Spring 现在似乎还不支持 Hibernate4。
            v = getHibernateTemplate().bulkUpdate(" update VisitOnline v set v.online=false where v.online=true and v.lastActiveDate<?", new Date(System.currentTimeMillis() - TIME_OUT));
        } catch (Throwable ex) {
            String msg = ex.getMessage();
        }
        return v;
        */
    }

    @Override
    public int getTotalCount(String hql) {
        //        List list = em.createQuery(hql).getResultList();
        //        if (list.size() > 0) {
        //            Number number = (Number) list.get(0);
        //            return number.intValue();
        //        }
        //        return 0;

        try {
            Session session = getSessionFactory().getCurrentSession();
            List list = session.createQuery(hql).list();
            if (list.size() > 0) {
                Number number = (Number) list.get(0);
                return number.intValue();
            }
        } catch (Exception ex) {
            String ms = ex.getMessage();

        }
        return 0;
    }

    @Override
    public List list(String hql, int firstResult, int maxResults) {
        //return em.createQuery(hql).setFirstResult(firstResult).setMaxResults(maxResult).getResultList();

        Session session = getSessionFactory().getCurrentSession();
        Query query = session.createQuery(hql);
        query.setFirstResult(firstResult).setMaxResults(maxResults);
        List list = query.list();
        return list;
    }

    @Override
    public VisitOnline findValidOnline(String ip, String userid) {
        Session session = getSessionFactory().getCurrentSession();
        List list = session.createQuery(" from VisitOnline v where v.online=true and v.ip=:ip and v.userid=:userid")
                .setParameter("ip", ip)
                .setParameter("userid", userid)
                .list();
        if (list.size() > 0) {
            return (VisitOnline) list.get(0);
        }
        return null;
    }

    //    public EntityManager getEm() {
    //        return em;
    //    }
    //
    //    public void setEm(EntityManager em) {
    //        this.em = em;
    //    }
}
